package com.hs.server.runnable;

import com.hs.server.config.MyConfig;
import com.hs.server.domain.VehQueuexxb;
import com.hs.server.service.VehQueuexxbService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;


/**
 * @Description
 * @Author: chenjiarui
 * @Date: 2021-07-14 16:15
 */
/**
 * @Description: 作业生产者，负责从数据库获取新作业并放入内存队列
 * @Author: chenjiarui
 * @Date: 2021-07-14 16:15
 */
@RequiredArgsConstructor
@Slf4j
@Component
public class WorkProducer implements Runnable {

    private final VehQueuexxbService vehQueuexxbService;
    // private final ShResourcexxService shResourcexxService; // 原始代码中注入但未使用，如果后续不需要，可以移除
    private final MyConfig myConfig;

    // 定义常量
    private static final int QUEUE_CAPACITY_THRESHOLD = 10; // 队列容量阈值
    private static final long CHECK_INTERVAL_MS = 100; // 检查队列的间隔时间（毫秒）
    private static final long OFFER_TIMEOUT_MS = 50; // 尝试向队列添加元素的超时时间（毫秒）

    @Override
    public void run() {
        log.info("WorkProducer 线程启动。");
        while (myConfig.openThread) {
            try {
                // 当作业队列的当前大小小于阈值时，尝试从数据库获取新作业
                if (myConfig.workQueue.size() < QUEUE_CAPACITY_THRESHOLD) {
                    VehQueuexxb vehQueuexxb = vehQueuexxbService.getNewWork();
                    if (vehQueuexxb != null) {
                        // 尝试将作业放入队列，设置超时时间，避免长时间阻塞
                        boolean offered = myConfig.workQueue.offer(vehQueuexxb, OFFER_TIMEOUT_MS, TimeUnit.MILLISECONDS);
                        if (offered) {
                            log.debug("成功将作业[{}]放入队列，当前队列大小: {}", vehQueuexxb.getLsh(), myConfig.workQueue.size());
                            // 更改作业表状态为已入队
                            int updatedRows = vehQueuexxbService.updateWorkReviewing(vehQueuexxb.getLsh(), vehQueuexxb.getZpzl());
                            if (updatedRows < 1) {
                                log.error("WorkProducer: 更改作业[{}-{}]状态为已入队失败，可能已被其他线程处理或数据不存在。",
                                        vehQueuexxb.getLsh(), vehQueuexxb.getZpzl());
                            } else {
                                log.info("WorkProducer: 作业[{}-{}]状态已更新为已入队。", vehQueuexxb.getLsh(), vehQueuexxb.getZpzl());
                            }
                        } else {
                            log.warn("WorkProducer: 队列已满或超时，未能将作业[{}]放入队列。", vehQueuexxb.getLsh());
                        }
                    } else {
                        log.debug("WorkProducer: 未获取到新的作业，等待下次检查。");
                    }
                } else {
                    log.debug("WorkProducer: 作业队列已达到或超过阈值[{}]，暂停生产，当前队列大小: {}.",
                            QUEUE_CAPACITY_THRESHOLD, myConfig.workQueue.size());
                }
                // 短暂休眠，避免CPU空转，控制生产速度
                Thread.sleep(CHECK_INTERVAL_MS);
            } catch (InterruptedException e) {
                // 捕获中断异常，通常表示线程被外部请求停止
                log.warn("WorkProducer 线程被中断，即将退出。", e);
                Thread.currentThread().interrupt(); // 恢复中断状态
                break; // 退出循环
            } catch (Exception e) {
                // 捕获其他运行时异常，记录错误并继续尝试
                log.error("WorkProducer 运行异常: ", e);
                // 可以在此处添加更复杂的错误处理逻辑，例如错误计数、告警等
                try {
                    Thread.sleep(CHECK_INTERVAL_MS * 2); // 异常时稍长休眠，避免频繁出错
                } catch (InterruptedException ie) {
                    log.warn("WorkProducer 异常休眠时被中断。", ie);
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }
        log.info("WorkProducer 线程停止。");
    }
}
